praxis 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -1
  3. data/.travis.yml +15 -2
  4. data/CHANGELOG.md +54 -1
  5. data/bin/praxis +49 -2
  6. data/lib/api_browser/Gruntfile.js +247 -90
  7. data/lib/api_browser/app/bower_components/angular-mocks/.bower.json +19 -0
  8. data/lib/api_browser/app/bower_components/angular-mocks/README.md +57 -0
  9. data/lib/api_browser/app/bower_components/angular-mocks/angular-mocks.js +2193 -0
  10. data/lib/api_browser/app/bower_components/angular-mocks/bower.json +9 -0
  11. data/lib/api_browser/app/bower_components/angular-mocks/package.json +27 -0
  12. data/lib/api_browser/app/bower_components/angular/.bower.json +6 -5
  13. data/lib/api_browser/app/bower_components/angular/README.md +23 -4
  14. data/lib/api_browser/app/bower_components/angular/angular-csp.css +6 -0
  15. data/lib/api_browser/app/bower_components/angular/angular.js +2287 -1597
  16. data/lib/api_browser/app/bower_components/angular/angular.min.js +212 -205
  17. data/lib/api_browser/app/bower_components/angular/angular.min.js.gzip +0 -0
  18. data/lib/api_browser/app/bower_components/angular/angular.min.js.map +3 -3
  19. data/lib/api_browser/app/bower_components/angular/bower.json +2 -1
  20. data/lib/api_browser/app/bower_components/angular/package.json +25 -0
  21. data/lib/api_browser/app/bower_components/showdown/.bower.json +39 -0
  22. data/lib/api_browser/app/bower_components/showdown/.jshintignore +2 -0
  23. data/lib/api_browser/app/bower_components/showdown/.travis.yml +8 -0
  24. data/lib/api_browser/app/bower_components/showdown/Gruntfile.js +100 -0
  25. data/lib/api_browser/app/bower_components/showdown/README.md +317 -0
  26. data/lib/api_browser/app/bower_components/showdown/bower.json +26 -0
  27. data/lib/api_browser/app/bower_components/showdown/compressed/Showdown.js +1606 -0
  28. data/lib/api_browser/app/bower_components/showdown/compressed/Showdown.js.map +1 -0
  29. data/lib/api_browser/app/bower_components/showdown/compressed/Showdown.min.js +2 -0
  30. data/lib/api_browser/app/bower_components/showdown/compressed/extensions/github.min.js +2 -0
  31. data/lib/api_browser/app/bower_components/showdown/compressed/extensions/github.min.js.map +1 -0
  32. data/lib/api_browser/app/bower_components/showdown/compressed/extensions/prettify.min.js +2 -0
  33. data/lib/api_browser/app/bower_components/showdown/compressed/extensions/prettify.min.js.map +1 -0
  34. data/lib/api_browser/app/bower_components/showdown/compressed/extensions/table.min.js +2 -0
  35. data/lib/api_browser/app/bower_components/showdown/compressed/extensions/table.min.js.map +1 -0
  36. data/lib/api_browser/app/bower_components/showdown/compressed/extensions/twitter.min.js +2 -0
  37. data/lib/api_browser/app/bower_components/showdown/compressed/extensions/twitter.min.js.map +1 -0
  38. data/lib/api_browser/app/bower_components/showdown/license.txt +34 -0
  39. data/lib/api_browser/app/bower_components/showdown/package.json +47 -0
  40. data/lib/api_browser/app/bower_components/showdown/src/extensions/github.js +25 -0
  41. data/lib/api_browser/app/bower_components/showdown/src/extensions/prettify.js +29 -0
  42. data/lib/api_browser/app/bower_components/showdown/src/extensions/table.js +106 -0
  43. data/lib/api_browser/app/bower_components/showdown/src/extensions/twitter.js +42 -0
  44. data/lib/api_browser/app/bower_components/showdown/src/ng-showdown.js +150 -0
  45. data/lib/api_browser/app/bower_components/showdown/src/showdown.js +1454 -0
  46. data/lib/api_browser/app/index.html +6 -4
  47. data/lib/api_browser/app/js/app.js +1 -2
  48. data/lib/api_browser/app/js/controllers/action.js +4 -4
  49. data/lib/api_browser/app/js/controllers/controller.js +1 -1
  50. data/lib/api_browser/app/js/controllers/menu.js +5 -3
  51. data/lib/api_browser/app/js/controllers/type.js +5 -5
  52. data/lib/api_browser/app/js/directives/attribute_description.js +5 -5
  53. data/lib/api_browser/app/js/directives/attribute_table.js +1 -1
  54. data/lib/api_browser/app/js/directives/attribute_table_row.js +2 -2
  55. data/lib/api_browser/app/js/directives/no_container.js +1 -1
  56. data/lib/api_browser/app/js/directives/request_body.js +5 -5
  57. data/lib/api_browser/app/js/directives/request_headers.js +3 -6
  58. data/lib/api_browser/app/js/directives/request_parameters.js +3 -6
  59. data/lib/api_browser/app/js/directives/type_label.js +4 -5
  60. data/lib/api_browser/app/js/factories/Documentation.js +4 -4
  61. data/lib/api_browser/app/js/factories/PayloadTemplates.js +2 -2
  62. data/lib/api_browser/app/js/factories/TypeTemplates.js +3 -3
  63. data/lib/api_browser/app/js/filters/markdown.js +6 -0
  64. data/lib/api_browser/app/js/filters/resource_name.js +2 -2
  65. data/lib/api_browser/app/sass/modules/_header.scss +2 -7
  66. data/lib/api_browser/app/sass/{main.scss → praxis.scss} +0 -0
  67. data/lib/api_browser/app/sass/variables/_bootstrap-variables.scss +370 -367
  68. data/lib/api_browser/app/views/action.html +2 -2
  69. data/lib/api_browser/app/views/controller.html +2 -2
  70. data/lib/api_browser/app/views/directives/attribute_description.html +1 -1
  71. data/lib/api_browser/app/views/layout.html +2 -11
  72. data/lib/api_browser/app/views/navbar.html +9 -0
  73. data/lib/api_browser/app/views/resource/_actions.html +1 -1
  74. data/lib/api_browser/app/views/type.html +2 -2
  75. data/lib/api_browser/app/views/type/_details.html +2 -1
  76. data/lib/api_browser/bower.json +5 -0
  77. data/lib/api_browser/package.json +18 -7
  78. data/lib/praxis.rb +8 -3
  79. data/lib/praxis/action_definition.rb +28 -6
  80. data/lib/praxis/api_definition.rb +30 -2
  81. data/lib/praxis/api_general_info.rb +36 -0
  82. data/lib/praxis/bootloader.rb +1 -0
  83. data/lib/praxis/collection.rb +34 -0
  84. data/lib/praxis/controller.rb +7 -0
  85. data/lib/praxis/dispatcher.rb +3 -0
  86. data/lib/praxis/links.rb +2 -8
  87. data/lib/praxis/media_type.rb +6 -24
  88. data/lib/praxis/media_type_collection.rb +6 -2
  89. data/lib/praxis/plugin_concern.rb +2 -1
  90. data/lib/praxis/request.rb +24 -15
  91. data/lib/praxis/request_stages/request_stage.rb +19 -4
  92. data/lib/praxis/request_stages/validate_params_and_headers.rb +1 -1
  93. data/lib/praxis/request_stages/validate_payload.rb +1 -1
  94. data/lib/praxis/resource_definition.rb +45 -10
  95. data/lib/praxis/response_definition.rb +46 -27
  96. data/lib/praxis/restful_doc_generator.rb +94 -7
  97. data/lib/praxis/simple_media_type.rb +2 -9
  98. data/lib/praxis/stage.rb +1 -4
  99. data/lib/praxis/tasks/api_docs.rb +51 -19
  100. data/lib/praxis/tasks/routes.rb +19 -15
  101. data/lib/praxis/types/media_type_common.rb +31 -0
  102. data/lib/praxis/types/multipart.rb +4 -4
  103. data/lib/praxis/version.rb +1 -1
  104. data/praxis.gemspec +2 -2
  105. data/spec/api_browser/factories/documentation_spec.js +50 -0
  106. data/spec/api_browser/filters/attribute_name_spec.js +23 -0
  107. data/spec/functional_spec.rb +62 -10
  108. data/spec/praxis/action_definition_spec.rb +12 -4
  109. data/spec/praxis/api_definition_spec.rb +159 -0
  110. data/spec/praxis/api_general_info_spec.rb +36 -0
  111. data/spec/praxis/bootloader_spec.rb +10 -1
  112. data/spec/praxis/media_type_collection_spec.rb +46 -53
  113. data/spec/praxis/media_type_spec.rb +6 -6
  114. data/spec/praxis/request_stage_spec.rb +7 -2
  115. data/spec/praxis/request_stages_validate_spec.rb +12 -7
  116. data/spec/praxis/resource_definition_spec.rb +62 -0
  117. data/spec/praxis/response_definition_spec.rb +26 -16
  118. data/spec/praxis/stage_spec.rb +4 -8
  119. data/spec/praxis/types/collection_spec.rb +144 -0
  120. data/spec/spec_app/app/controllers/instances.rb +8 -2
  121. data/spec/spec_app/design/api.rb +11 -0
  122. data/spec/spec_app/design/media_types/instance.rb +12 -0
  123. data/spec/spec_app/design/media_types/volume.rb +9 -2
  124. data/spec/spec_app/design/media_types/volume_snapshot.rb +9 -6
  125. data/spec/spec_app/design/resources/instances.rb +25 -10
  126. data/spec/support/spec_media_types.rb +1 -1
  127. data/spec/support/spec_resource_definitions.rb +2 -0
  128. data/tasks/thor/app.rb +15 -10
  129. data/tasks/thor/example.rb +115 -115
  130. data/tasks/thor/templates/generator/empty_app/.gitignore +2 -0
  131. data/tasks/thor/templates/generator/empty_app/docs/app.js +1 -0
  132. data/tasks/thor/templates/generator/empty_app/docs/styles.scss +3 -0
  133. metadata +50 -9
  134. data/lib/api_browser/app/css/main.css +0 -4511
  135. data/lib/praxis/types/collection.rb +0 -17
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4684312c88071162f3525b9ee7c88c9f9a7587d2
4
- data.tar.gz: fcf53c832ebc5f430dc37b9944ccc334b7ec3678
3
+ metadata.gz: 969f34805663e8986a5ac60e86216c3139324d98
4
+ data.tar.gz: 8fb76988854889627663ff66874ecb1a8f4549b0
5
5
  SHA512:
6
- metadata.gz: a600f9e9857b338f87c3dbec975e016a7f3bee940b0a9c590cfc241e7b05e81825877a92a6b49049089ef76ecabcf127ef978d3d545d828b8d7ce197a0b792d8
7
- data.tar.gz: 115db171ee75c4569beab2277e4c917bcd768e444e264b769862373936365a54cff1eaa154c21cf7543b59816756e45aafddbc0dd0c95714afdc392f95cae006
6
+ metadata.gz: 228bc86fd20fef3ad70b282519266378b6f90333e36438923b5a5ed8c416ccacf7d5ac4444bab3d675a2bdd210a3cb89a62090d3ce780d2a5c62cc9c848216d1
7
+ data.tar.gz: b355e2bd55fe51389ba695d8348303560208d960694f8832d74ebf59942b3e9088cf757c48ae37109b975d6dac238815f15528457c32655c2baa3c3c9b7cf290
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.1.2
1
+ 2.1.5
data/.travis.yml CHANGED
@@ -1,5 +1,18 @@
1
1
  language: ruby
2
2
  cache: bundler
3
3
  rvm:
4
- - "2.1.2"
5
- script: bundle exec rspec spec
4
+ - "2.1.5"
5
+ node_js:
6
+ - "0.10"
7
+ branches:
8
+ only:
9
+ - master
10
+ before_install:
11
+ - cd lib/api_browser
12
+ - npm install
13
+ - cd ../..
14
+ script:
15
+ - bundle exec rspec spec
16
+ - cd lib/api_browser
17
+ - npm test
18
+ - cd ../..
data/CHANGELOG.md CHANGED
@@ -2,8 +2,60 @@
2
2
 
3
3
  ## next
4
4
 
5
- ## 0.13.0
5
+ ## 0.14.0
6
+
7
+ * Adds features for customizing and exporting the Doc browser, namely the following changes:
8
+ 1. All doc browser stuff is now centralised under the `praxis:docs` namespace.
9
+ 2. The doc browser requires node.js. (TODO: add this to the docs PR)
10
+ 3. `rake praxis:docs:generate` generates the JSON schema files. `rake praxis:api_docs` is now an alias of this with the idea that `rake praxis:api_docs` will be deprecated.
11
+ 4. `rake praxis:docs:preview` will open a browser window with the doc browser. It will refresh automatically when the design files change as well as when any customisations change.
12
+ 5. `rake praxis:docs:build` will generate a fully built static version of the app in `docs/output`. This can then be put on S3 or GH pages and should work.
13
+ 6. The default app generator will now generate a docs directory with some files to get you started.
14
+ 7. Any `.js` file in the `docs` directory will be included in the doc browser. Angular's dependency injection allows users to override any service or controller as needed.
15
+ 8. The default `docs/styles.scss` simply `@import 'praxis'`. However this means the user can override any of bootstraps variables allowing for easy theme customisation. Rules etc. can now also be overridden.
16
+ 9. Any templates defined in `docs/views` take precedence over those defined in the doc browser. This means the user can easily customise parts of the app, while leaving the rest up to us.
17
+ 10. Any changes to the above customisations will be automatically reloaded on save.
18
+ * First pass at describing (and doc-generating) API global information
19
+ * Inside a `Praxis::ApiDefinition.define` block one can now specify a few things about the API by using:
20
+ * info("1.0") `<block>` - Which will apply to a particular version only
21
+ * info `<block>` - Which will be inherited by any existing API version
22
+ * The current pieces of information that can be defined in the block are: `name`, `title`, `description` and `basepath`. See [this](https://github.com/rightscale/praxis/blob/master/spec/spec_app/design/api.rb) for details
23
+ * NOTE: This information is output to the JSON files, BUT not used in the doc browser yet.
24
+ * Changed the doc generation and browser to use "ids" instead of "names" for routes and generated files.
25
+ * Currently, "ids" are generated using dashes instead of double colons (instead of random ids). This closes issue #31.
26
+ * Added the definition and handling of canonical urls for API resources
27
+ * One can now specify which action URL should be considered as the canonical resource href:
28
+ * by using `canonical_path <action_name>` at the top of the resource definition class
29
+ * See the [instances](https://github.com/rightscale/praxis/blob/master/spec/spec_app/design/resources/instances.rb) resource definition for an example.
30
+ * With a canonical href defined, one can then both generate and parse them by using:
31
+ * `.to_href(<named arguments hash>) => <href String>`
32
+ * `.parse_href( <href String> ) => < named arguments hash >`. Note: The returned arguments are properly typed-coerced.
33
+ * These helpers can be accessed from:
34
+ * the `definition` object in the controller instance (i.e., `self.definition.to_href(id: 1). )
35
+ * or through the class-level methods in the resource definition (i.e. `MyApiResource.parse_href("/my_resource/1")` )
36
+ * Hooked up rake tasks into the `praxis` binary for convenience. In particular
37
+ * praxis routes [json]
38
+ * praxis docs [browser]
39
+ * praxis console
40
+ * Added `MediaTypeCommon` module, which contains the `identifier`, `description`, and `describe` methods formerly found in `MediaType`. This is now the module used for checking whether a given class should be included in generated documentation, or is valid for use in a `ResponseDefinition`
41
+ * Improved `Praxis::Collection.of` when used with MediaTypes
42
+ * It will now define an inner `<media_type>::Collection` type that is an `Attributor::Collection` of the MediaType that also will include the `MediaTypeCommon` module.
43
+ * By default, Praxis will take the identifier of the parent `MediaType` and append a `collection=true` suffix to it.
44
+ * Fixed `ResponseDefinition` Content-Type validation to properly handle parameters (i.e., "application/json;collection=true").
45
+ * Note: For "index" type actions, this now means Praxis will properly validate any 'collection=true' parameter specified in the `ResponseDefintion` and set by the controller.
46
+ * Deprecated `MediaTypeCollection`. Please define separate classes and attributes for "collection" and "summary" uses.
47
+ * Improved code for stages
48
+ * `setup!` is no longer called within the `run` default code of a stage
49
+ * removed unnecessary raise error when substages are empty (while not common it can be possible, and totally valid)
50
+ * Add `Response` to supported classes in `PluginConcern`
51
+ * Fix doc generation to use `ids` for top-level types (rather than names) so they are correctly linkable.
52
+ * Doc Browser: Added support for Markdown rendering of descriptions (for resources, media_types, attributes, etc...)
53
+ * Added test framework for the doc browser. Run the tests with `grunt test` from lib/api_browser.
54
+ * Enhanced the `praxis:docs:preview` rake task with an optional port parameter
55
+ * Fixed praxis:routes rake task to support actions that do not have routes defined
56
+ * Added `:source` to `ActionDefinition` parameter descriptions with the value of either 'url' or 'query' to denote where the parameter is (typically) extracted from. Note: not currently shown in doc browser.
6
57
 
58
+ ## 0.13.0
7
59
  * Added `nodoc!` method to `ActionDefinition`, `ResourceDefinition` to hide actions and resources from the generated documentation.
8
60
  * Default HTTP responses:
9
61
  * Added descriptions
@@ -24,6 +76,7 @@
24
76
  * This is not compatible if it also wants to use the `links` DSL.
25
77
 
26
78
 
79
+
27
80
  ## 0.11.2
28
81
 
29
82
  * The Doc Browser will now not change the menu when refreshing.
data/bin/praxis CHANGED
@@ -2,12 +2,59 @@
2
2
 
3
3
  require 'bundler'
4
4
 
5
+ Bundler.setup :default, :test
6
+ Bundler.require :default, :test
7
+
8
+
9
+ if ["routes","docs","console"].include? ARGV[0]
10
+ require 'rake'
11
+ require 'praxis'
12
+ require 'praxis/tasks'
13
+
14
+ case ARGV[0]
15
+ when "routes"
16
+ Rake::Task['praxis:routes'].invoke(ARGV[1])
17
+ when "docs"
18
+ task_name = case ARGV[1]
19
+ when nil,'browser'
20
+ 'praxis:docs:preview'
21
+ when 'generate'
22
+ 'praxis:docs:generate'
23
+ when 'package'
24
+ 'praxis:docs:build'
25
+ end
26
+ # task_name = ARGV[1] == 'browser' ? 'praxis:doc_browser' : 'praxis:api_docs'
27
+ Rake::Task[task_name].invoke
28
+ when "console"
29
+ Rake::Task['praxis:console'].invoke
30
+ end
31
+ exit 0
32
+ end
33
+ # Thor tasks
5
34
  path_to_praxis = File.expand_path(File.dirname(File.dirname(__FILE__)))
6
35
  path_to_loader = '%s/tasks/loader.thor' % path_to_praxis
7
36
 
8
37
  load path_to_loader
9
38
 
10
39
  class PraxisGenerator < Thor
40
+
41
+ # Include a few fake thor action descriptions (for the rake tasks above) so they can show up in the same usage messages
42
+ desc "routes [json]", "Prints the route table of the application. Defaults to table format, but can produce json"
43
+ def routes
44
+ end
45
+
46
+ desc "docs [generate|browser|package]", <<-EOF
47
+ Generates API documentation and a Web App to inspect it
48
+ generate - Generates the JSON docs
49
+ browser - (default) Generates JSON docs, and automatically starts a Web app to browse them.
50
+ package - Generates JSON docs, and neatly packages all the necessary static files ready for exporting the browsing app.
51
+ EOF
52
+ def docs
53
+ end
54
+
55
+ desc "console", "Open a console to the application, with its environment loaded"
56
+ def console
57
+ end
11
58
 
12
59
  # Simple helper to go get the existing description for the real action
13
60
  # Usage must still be provided rather than retrieved (since it is not a
@@ -33,7 +80,7 @@ class PraxisGenerator < Thor
33
80
  def generate(app_name)
34
81
  warn "This is a deprecated method.\nTo generate a hello world example, please use:\n praxis example #{app_name} "
35
82
  end
83
+
36
84
  end
37
-
38
-
85
+
39
86
  PraxisGenerator.start(ARGV)
@@ -3,13 +3,24 @@ module.exports = function(grunt) {
3
3
  require('load-grunt-tasks')(grunt);
4
4
 
5
5
  // Time how long tasks take. Can help when optimizing build times
6
- require('time-grunt')(grunt);
6
+ try {
7
+ require('time-grunt')(grunt);
8
+ } catch(e) {
9
+
10
+ }
11
+
12
+ var userDocsPath = process.env.USER_DOCS_PATH,
13
+ buildPath = userDocsPath + '/output',
14
+ browserPort = process.env.DOC_PORT || '9090';
15
+
16
+ var cssOutput = {};
17
+ cssOutput[buildPath + '/css/main.css'] = userDocsPath + '/styles.scss';
7
18
 
8
19
  grunt.initConfig({
9
20
  // web server for development
10
21
  connect: {
11
22
  options: {
12
- port: '9090',
23
+ port: browserPort,
13
24
  hostname: '0.0.0.0'
14
25
  },
15
26
  livereload: {
@@ -17,6 +28,7 @@ module.exports = function(grunt) {
17
28
  livereload: 9091,
18
29
  open: true,
19
30
  base: [
31
+ userDocsPath,
20
32
  '.tmp',
21
33
  '.data',
22
34
  'app'
@@ -25,77 +37,38 @@ module.exports = function(grunt) {
25
37
  },
26
38
  dist: {
27
39
  options: {
28
- base: ['.data', 'dist']
40
+ base: ['.data', buildPath]
29
41
  }
30
42
  }
31
43
  },
32
44
 
33
45
  clean: {
34
- dist: {
46
+ serve: {
35
47
  files: [{
36
48
  dot: true,
37
49
  src: [
38
- '.tmp',
39
- 'dist/*',
40
- '!dist/.git*'
50
+ '.tmp'
41
51
  ]
42
52
  }]
43
- }
44
- },
45
-
46
- // Watches files for changes
47
- watch: {
48
- // Reload stuff when the grunt file changes
49
- config: {
50
- files: ['Gruntfile.js'],
51
- tasks: 'prep',
52
- options: {
53
- reload: true
54
- }
55
- },
56
-
57
- // Updates index.html for any file added or removed
58
- scripts: {
59
- files: ['app/js/**/*.js'],
60
- tasks: 'fileblocks:scripts',
61
- options: { livereload: 9091 }
62
- },
63
-
64
- // Updates index.html for any bower component added or removed
65
- bowerComponents: {
66
- files: ['app/bower_components/**/*'],
67
- tasks: 'wiredep',
68
- options: { livereload: 9091 }
69
53
  },
70
-
71
- // Rebuild the stylesheets for any SASS file changed
72
- sass: {
73
- files: [
74
- 'app/sass/**/*.scss',
75
- 'app/bower_components/**/*.scss'
76
- ],
77
- tasks: 'sass',
78
- options: { livereload: 9091 }
79
- },
80
-
81
- // Watches files that don't need processing
82
- other: {
83
- files: [
84
- 'app/css/*.css',
85
- "app/index.html",
86
- "app/views/**/*.html"
87
- ],
54
+ dist: {
88
55
  options: {
89
- livereload: 9091
90
- }
56
+ force: true,
57
+ },
58
+ files: [{
59
+ dot: true,
60
+ src: [
61
+ '.tmp',
62
+ buildPath
63
+ ]
64
+ }]
91
65
  }
92
66
  },
93
-
94
67
  // Automatically inject Bower components into the app
95
68
  wiredep: {
96
69
  app: {
97
- src: 'app/index.html',
98
- ignorePath: 'app/',
70
+ src: '.tmp/index.html',
71
+ ignorePath: /(..\/)?app\//,
99
72
  // We do not use bootstrap's JS code, also the SASS styles are included by our style sheet
100
73
  exclude: [/bootstrap-sass/]
101
74
  }
@@ -104,13 +77,34 @@ module.exports = function(grunt) {
104
77
  // Automatically inject the JS files into the app
105
78
  fileblocks: {
106
79
  options: { removeFiles: true },
107
- scripts: {
80
+ dist: {
81
+ src: 'app/index.html',
82
+ dest: '.tmp/index.html',
83
+ blocks: {
84
+ scripts: {
85
+ cwd: 'app',
86
+ // This ensures app.js comes first so the angular module is declared
87
+ src: ['js/app.js', 'js/**/*.js']
88
+ },
89
+ userscripts: {
90
+ // cwd: userDocsPath,
91
+ src: [userDocsPath + '/app.js', userDocsPath + '/**/*.js', '!' + userDocsPath + '/output/**/*.js']
92
+ }
93
+ }
94
+ },
95
+
96
+ serve: {
108
97
  src: 'app/index.html',
98
+ dest: '.tmp/index.html',
109
99
  blocks: {
110
100
  scripts: {
111
101
  cwd: 'app',
112
102
  // This ensures app.js comes first so the angular module is declared
113
103
  src: ['js/app.js', 'js/**/*.js']
104
+ },
105
+ userscripts: {
106
+ cwd: userDocsPath,
107
+ src: ['app.js', '**/*.js', '!output/**/*.js']
114
108
  }
115
109
  }
116
110
  }
@@ -121,29 +115,28 @@ module.exports = function(grunt) {
121
115
  server: {
122
116
  options: {
123
117
  sourceComments: 'map',
124
- sourceMap: 'app/css/main.css.map'
118
+ sourceMap: __dirname + '/.tmp/css/main.css.map',
119
+ includePaths: ['app/sass']
125
120
  },
126
121
  files: {
127
- 'app/css/main.css': 'app/sass/main.scss'
122
+ '.tmp/css/main.css': userDocsPath + '/styles.scss'
128
123
  }
129
124
  },
130
125
  dist: {
131
126
  options: {
132
- sourceComments: 'none'
127
+ sourceComments: 'none',
128
+ includePaths: ['app/sass']
133
129
  },
134
- files: {
135
- 'dist/css/main.css': 'app/sass/main.scss'
136
- }
130
+ files: cssOutput
137
131
  }
138
132
  },
139
133
 
140
134
  cssmin: {
141
135
  dist: {
142
- files: {
143
- 'dist/css/main.css': [
144
- 'dist/css/main.css'
145
- ]
146
- }
136
+ files: [{
137
+ src: buildPath + '/css/main.css',
138
+ dest: buildPath + '/css/main.css'
139
+ }]
147
140
  }
148
141
  },
149
142
 
@@ -152,7 +145,7 @@ module.exports = function(grunt) {
152
145
  files: [{
153
146
  expand: true,
154
147
  cwd: '.tmp/concat/scripts',
155
- src: 'scripts.js',
148
+ src: '*.js',
156
149
  dest: '.tmp/concat/scripts'
157
150
  }]
158
151
  }
@@ -161,8 +154,8 @@ module.exports = function(grunt) {
161
154
  filerev: {
162
155
  dist: {
163
156
  src: [
164
- 'dist/scripts/*.js',
165
- 'dist/css/*.css'
157
+ buildPath + '/scripts/*.js',
158
+ buildPath + '/css/*.css'
166
159
  ]
167
160
  }
168
161
  },
@@ -179,16 +172,27 @@ module.exports = function(grunt) {
179
172
  removeScriptTypeAttributes: true,
180
173
  removeStyleLinkTypeAttributes: true
181
174
  },
182
- module: 'docBrowser',
183
175
  bootstrap: function(module, script) {
184
176
  return 'angular.module("' + module + '").run(function($templateCache){' + script + '});';
185
177
  },
186
- usemin: 'dist/scripts/scripts.js'
187
178
  },
188
179
  dist: {
189
180
  cwd: 'app',
190
181
  src: 'views/**/*.html',
191
- dest: '.tmp/templates.js'
182
+ dest: '.tmp/templates.js',
183
+ options: {
184
+ usemin: buildPath + '/scripts/praxis.js',
185
+ module: 'PraxisDocBrowser',
186
+ }
187
+ },
188
+ userScripts: {
189
+ cwd: userDocsPath,
190
+ src: 'views/**/*.html',
191
+ dest: '.tmp/usertemplates.js',
192
+ options: {
193
+ usemin: buildPath + '/scripts/docs.js',
194
+ module: 'DocBrowser',
195
+ }
192
196
  }
193
197
  },
194
198
 
@@ -198,10 +202,25 @@ module.exports = function(grunt) {
198
202
  expand: true,
199
203
  dot: true,
200
204
  cwd: 'app',
201
- dest: 'dist',
205
+ dest: buildPath,
206
+ src: [
207
+ '*.{ico,png,txt}'
208
+ ]
209
+ }, {
210
+ expand: true,
211
+ dot: true,
212
+ cwd: '.tmp',
213
+ dest: buildPath,
202
214
  src: [
203
- '*.{ico,png,txt}',
204
- 'index.html',
215
+ 'index.html'
216
+ ]
217
+ }, {
218
+ expand: true,
219
+ dot: true,
220
+ cwd: userDocsPath,
221
+ dest: buildPath,
222
+ src: [
223
+ 'api/**'
205
224
  ]
206
225
  }]
207
226
  }
@@ -211,36 +230,146 @@ module.exports = function(grunt) {
211
230
  // concat, minify and revision files. Creates configurations in memory so
212
231
  // additional tasks can operate on them
213
232
  useminPrepare: {
214
- html: 'app/index.html',
233
+ html: '.tmp/index.html',
215
234
  options: {
216
- dest: 'dist'
235
+ dest: buildPath
217
236
  }
218
237
  },
219
238
 
220
239
  // Performs rewrites based on rev and the useminPrepare configuration
221
240
  usemin: {
222
- html: ['dist/{,*/}*.html'],
223
- css: ['dist/css/{,*/}*.css'],
241
+ html: [buildPath + '/index.html'],
242
+ css: [buildPath + '/css/{,*/}*.css'],
243
+ options: {
244
+ assetsDirs: [buildPath]
245
+ }
246
+ },
247
+
248
+ karma: {
224
249
  options: {
225
- assetsDirs: ['dist']
250
+ files: [
251
+ 'node_modules/quick_check/dist/jasmine-quick-check.js',
252
+ 'app/bower_components/jquery/dist/jquery.js',
253
+ 'app/bower_components/angular/angular.js',
254
+ 'app/bower_components/lodash/dist/lodash.compat.js',
255
+ 'app/bower_components/angular-ui-router/release/angular-ui-router.js',
256
+ 'app/bower_components/angular-ui-bootstrap-bower/ui-bootstrap-tpls.js',
257
+ 'app/bower_components/angular-sanitize/angular-sanitize.js',
258
+ 'app/bower_components/angular-mocks/angular-mocks.js',
259
+ 'app/js/app.js', 'app/js/**/*.js', '.tmp/templates.js', '../../spec/api_browser/**/*.js'
260
+ ],
261
+ frameworks: ['jasmine'],
262
+ reporters: ['dots'],
263
+ },
264
+ unit: {
265
+ browsers: ['PhantomJS'],
266
+ singleRun: true
267
+ }
268
+ },
269
+
270
+ jshint: {
271
+ src: ['app/js/**/*.js', '../../spec/api_browser/**/*.js'],
272
+ options: {
273
+ bitwise: true,
274
+ immed: true,
275
+ newcap: false,
276
+ noarg: true,
277
+ noempty: true,
278
+ nonew: true,
279
+ trailing: true,
280
+ boss: true,
281
+ eqnull: true,
282
+ expr: true,
283
+ laxbreak: true,
284
+ loopfunc: true,
285
+ sub: true,
286
+ undef: true,
287
+ unused: true,
288
+ browser: true,
289
+ quotmark: true,
290
+ indent: 2,
291
+ jasmine: true,
292
+ globals: {
293
+ "angular": false,
294
+ "app": true,
295
+ "_": false,
296
+ "$": false,
297
+ "jQuery": false,
298
+ "Showdown": false,
299
+ "inject": false,
300
+ "qc": false
301
+ }
226
302
  }
227
303
  }
228
304
  });
229
305
 
230
- // Prepares the assets (used by watch:config)
231
- grunt.registerTask('prep', [
232
- 'fileblocks',
233
- 'wiredep',
234
- 'sass'
235
- ]);
306
+ grunt.registerTask('runGenerator', function() {
307
+ var exec = require('child_process').exec;
308
+ var done = this.async();
309
+ exec('bundle exec rake praxis:docs:generate', {cwd: userDocsPath + '/../'}, done);
310
+ });
236
311
 
237
312
  grunt.registerTask('serve', function(target) {
238
313
  if (target === 'dist') {
239
314
  return grunt.task.run(['build', 'connect:dist:keepalive']);
240
315
  }
241
316
 
317
+ grunt.config.merge({
318
+ watch: {
319
+ // Updates index.html for any file added or removed
320
+ scripts: {
321
+ files: ['app/js/**/*.js', userDocsPath + '/**/*.js'],
322
+ tasks: 'fileblocks:serve',
323
+ options: { livereload: 9091 }
324
+ },
325
+
326
+ // Updates index.html for any bower component added or removed
327
+ bowerComponents: {
328
+ files: ['app/bower_components/**/*', userDocsPath + '/bower_components/**/*'],
329
+ tasks: 'wiredep',
330
+ options: { livereload: 9091 }
331
+ },
332
+
333
+ // Rebuild the stylesheets for any SASS file changed
334
+ sass: {
335
+ files: [
336
+ 'app/sass/**/*.scss',
337
+ 'app/bower_components/**/*.scss',
338
+ userDocsPath + '/**/*.scss'
339
+ ],
340
+ tasks: 'sass',
341
+ options: { livereload: 9091 }
342
+ },
343
+
344
+ data: {
345
+ files: [
346
+ userDocsPath + '/../design/**/*.rb'
347
+ ],
348
+ tasks: 'runGenerator',
349
+ options: { livereload: 9091 }
350
+ },
351
+
352
+ // Watches files that don't need processing
353
+ other: {
354
+ files: [
355
+ 'app/css/*.css',
356
+ "app/index.html",
357
+ "app/views/**/*.html",
358
+ userDocsPath + '/views/**/*.html'
359
+ ],
360
+ options: {
361
+ livereload: 9091
362
+ }
363
+ }
364
+ }
365
+ });
366
+
367
+
242
368
  grunt.task.run([
243
- 'prep',
369
+ 'clean:serve',
370
+ 'fileblocks:serve',
371
+ 'wiredep',
372
+ 'sass:server',
244
373
  'connect:livereload',
245
374
  'watch'
246
375
  ]);
@@ -248,7 +377,9 @@ module.exports = function(grunt) {
248
377
 
249
378
  grunt.registerTask('build', [
250
379
  'clean:dist',
251
- 'prep',
380
+ 'fileblocks:dist',
381
+ 'wiredep',
382
+ 'sass:dist',
252
383
  'useminPrepare',
253
384
  'ngtemplates',
254
385
  'concat',
@@ -260,5 +391,31 @@ module.exports = function(grunt) {
260
391
  'usemin'
261
392
  ]);
262
393
 
394
+ grunt.registerTask('test', function() {
395
+ grunt.config.set('watch', {
396
+ tests: {
397
+ files: [
398
+ 'app/js/**',
399
+ '../../spec/api_browser/**'
400
+ ],
401
+ tasks: ['jshint:src', 'karma:unit'],
402
+ options: {
403
+ atBegin: true
404
+ }
405
+ }
406
+ });
407
+
408
+ grunt.task.run([
409
+ 'ngtemplates:dist',
410
+ 'watch:tests'
411
+ ]);
412
+ });
413
+
414
+ grunt.registerTask('ci', [
415
+ 'ngtemplates:dist',
416
+ 'jshint:src',
417
+ 'karma:unit'
418
+ ]);
419
+
263
420
  grunt.registerTask("default", ["serve"]);
264
421
  };